package com.lanchetech.merchant.service.impl;


import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lanchetech.bean.dto.TenantFeatureDTO;
import com.lanchetech.bean.request.PageReq;
import com.lanchetech.bean.request.ShopAmountReq;
import com.lanchetech.bean.request.TenantFeatureReq;
import com.lanchetech.bean.response.BasePageResp;
import com.lanchetech.bean.response.BaseResp;
import com.lanchetech.bean.response.KdzsCallBackResp;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.bean.vo.*;
import com.lanchetech.common.enums.*;
import com.lanchetech.common.exception.ResultCodeException;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.merchant.config.JwtTokenUtil;
import com.lanchetech.merchant.service.StoreService;
import com.lanchetech.service.DaoService;
import com.raycloud.open.sdk.api.base.utils.SignUtils;
import org.hashids.Hashids;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

import static com.lanchetech.common.constants.JypConstant.INIT_TENANT_ID;

@Service
public class StoreServiceImpl implements StoreService {

    @Autowired
    TenantMapper tenantMapper;

    @Autowired
    AreaMapper areaMapper;

    @Autowired
    RecommendSpuMapper recommendSpuMapper;

    @Autowired
    SpuMapper spuMapper;

    @Autowired
    DaoService daoService;

    @Autowired
    CustomPageMapper customPageMapper;

    @Autowired
    CustomPageDataMapper customPageDataMapper;

    @Autowired
    TenantConfigMapper tenantConfigMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    ShopAmountMapper shopAmountMapper;

    @Autowired
    ShopCollectionMapper shopCollectionMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private IdentityMapper identityMapper;
    @Autowired
    ShopMapper shopMapper;

    private String appKey = "93CAB43C30E34F53B98D18E83FBFBE49";

    private String appSecret = "1AA8203422C948EE9419133730E76BFB";

    /**
     * 模糊删除redis，支持通配符
     *
     * @param key
     */
    private void deleteRedisByKey(String key) {
        Set<String> keys = redisTemplate.keys(key);
        if (!CollectionUtils.isEmpty(keys)) {
            redisTemplate.delete(keys);
        }
    }


    @Override
    public ResultData<Shop> getShopDetail(Merchant merchant) {
        Shop shop = shopMapper.selectByPrimaryKey(merchant.getTenantId());
        return new ResultData(shop);
    }

    @Override
    public ResultData<Tenant> getContract(Merchant merchant) {
        Tenant tenant = null;
        if (merchant.getTenantId().equals(INIT_TENANT_ID)) {
            // 如果未签约成功
            tenant = tenantMapper.findOneByMerchantId(merchant.getId());
        } else {
            // 如果已经签约成功
            tenant = tenantMapper.selectByPrimaryKey(merchant.getTenantId());
        }
        return new ResultData(tenant);
    }

    @Override
    public ResultData<Long> editContract(Tenant req, Integer step) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Tenant tenant = new Tenant();
        if (req.getId() == null) {
            tenant.setMerchantId(merchant.getId());
            tenant.setAvatar(req.getAvatar());
            tenant.setTenantName(req.getTenantName());
            tenant.setTenantNickname(req.getTenantNickname());
            tenant.setContactName(req.getContactName());
            tenant.setEmail(req.getEmail());
            tenant.setPhone(req.getPhone());
            tenant.setStatus(ToggleEnum.ON.getStatus());
            tenant.setPoint(BigDecimal.ZERO);
            tenant.setCoin(BigDecimal.ZERO);
            tenant.setDeleted(DeletedEnum.DEFAULT.getStatus());
            tenant.setAuditStatus(TenantAuditStatusEnum.EDITING.getStatus());
            tenant.setCreatedAt(new Date());
            tenant.setUpdatedAt(new Date());
            // 综合评分，若为0则是暂无评分
            tenant.setStar(0D);
            tenantMapper.insert(tenant);
        } else {
            tenant = tenantMapper.selectByPrimaryKey(req.getId());
            if (step.equals(0)) {
                tenant.setAvatar(req.getAvatar());
                tenant.setTenantName(req.getTenantName());
                tenant.setTenantNickname(req.getTenantNickname());
                tenant.setContactName(req.getContactName());
                tenant.setEmail(req.getEmail());
                tenant.setPhone(req.getPhone());
                tenant.setAuditStatus(TenantAuditStatusEnum.EDITING.getStatus());
                tenant.setUpdatedAt(new Date());
                tenantMapper.updateByPrimaryKeySelective(tenant);
            }
            if (step.equals(1)) {
                Area area = areaMapper.selectByPrimaryKey(req.getArea());
                if (area != null) {
                    tenant.setMergerName(area.getMergerName());
                }
                tenant.setProvince(req.getProvince());
                tenant.setCity(req.getCity());
                tenant.setArea(req.getArea());
                tenant.setAddress(req.getAddress());
                tenant.setAuditStatus(TenantAuditStatusEnum.EDITING.getStatus());
                tenant.setUpdatedAt(new Date());
                tenantMapper.updateByPrimaryKeySelective(tenant);
            }
            if (step.equals(2)) {
                tenant.setLicenseImage(req.getLicenseImage());
                tenant.setLicenseNumber(req.getLicenseNumber());
                tenant.setLicenseName(req.getLicenseName());
                tenant.setLicenseValidTime(req.getLicenseValidTime());
                tenant.setLicenseLongTerm(req.getLicenseLongTerm());
                tenant.setIdCardPositive(req.getIdCardPositive());
                tenant.setIdCardBack(req.getIdCardBack());
                tenant.setIdCardName(req.getIdCardName());
                tenant.setAuditStatus(TenantAuditStatusEnum.EDITING.getStatus());
                tenant.setUpdatedAt(new Date());
                tenantMapper.updateByPrimaryKeySelective(tenant);
            }
            if (step.equals(3)) {
                tenant.setBank(req.getBank());
                tenant.setAccount(req.getAccount());
                tenant.setOpenBank(req.getOpenBank());
                tenant.setOpenName(req.getOpenName());
                tenant.setAuditStatus(TenantAuditStatusEnum.PENDING.getStatus());
                tenant.setUpdatedAt(new Date());
                tenantMapper.updateByPrimaryKeySelective(tenant);
            }
        }
        return new ResultData<>(tenant.getId());
    }

    @Override
    public BaseResp editTenantDescription(Merchant merchant, Tenant tenant) {
        if (merchant.getTenantId().equals(tenant.getId())) {
            tenantMapper.updateDescriptionById(tenant.getDescription(), tenant.getId());
        } else {
            return new BaseResp(ResultCode.FAIL);
        }
        return new BaseResp();
    }

    @Override
    public BaseResp editTenantImageUrl(Merchant merchant, Tenant tenant) {
        if (merchant.getTenantId().equals(tenant.getId())) {
            tenantMapper.updateImageUrlById(tenant.getImageUrl(), tenant.getId());
        } else {
            return new BaseResp(ResultCode.FAIL);
        }
        return new BaseResp();
    }

    @Override
    public BaseResp editStoreRecommendSpu(Merchant merchant, List<Long> spuIds) {
        // 先删除
        recommendSpuMapper.deleteByTenantId(merchant.getTenantId());

        if (!CollectionUtils.isEmpty(spuIds)) {
            if (spuIds.size() <= 6) {
                // 再插入
                List<RecommendSpu> recommendSpuList = new ArrayList<>();
                spuIds.stream().forEach(item -> {
                    recommendSpuList.add(RecommendSpu.builder()
                            .spuId(item)
                            .tenantId(merchant.getTenantId())
                            .build());
                });
                recommendSpuMapper.batchInsert(recommendSpuList);
            } else {
                return new BaseResp(ResultCode.RECOMMEND_SPU_EXCEEDED);
            }
        }
        return new BaseResp();
    }

    @Override
    public BaseResp editTenantFeature(Merchant merchant, TenantFeatureReq req) {
        if (merchant.getTenantId().equals(req.getId())) {
            Tenant tenant = tenantMapper.selectByPrimaryKey(req.getId());
            TenantFeatureDTO dto = JSON.parseObject(tenant.getFeature(), TenantFeatureDTO.class);
            if (dto == null) {
                dto = new TenantFeatureDTO();
            }
            if ("recommendCustomPageId".equals(req.getField())) {
                dto.setRecommendCustomPageId(new Long(req.getValue()));
            }
            if ("newCustomPageId".equals(req.getField())) {
                dto.setNewCustomPageId(new Long(req.getValue()));
            }
            if ("activityCustomPageId".equals(req.getField())) {
                dto.setActivityCustomPageId(new Long(req.getValue()));
            }
            if ("display".equals(req.getField())) {
                dto.setDisplay(JSON.parseArray(req.getValue(), String.class));
            }
            tenantMapper.updateFeatureById(JSON.toJSONString(dto), tenant.getId());
        } else {
            return new BaseResp(ResultCode.FAIL);
        }
        return new BaseResp();
    }

    @Override
    public ResultData<List<Spu>> getRecommendSpuList(Merchant merchant) {
        List<RecommendSpu> recommendSpuList = recommendSpuMapper.findAllByTenantId(merchant.getTenantId());
        List<Spu> spuList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(recommendSpuList)) {
            spuList = spuMapper.findAllByIds(recommendSpuList.stream().map(RecommendSpu::getSpuId).collect(Collectors.toList()));
        }
        return new ResultData<>(spuList);
    }


    @Override
    public BaseResp editCustomPage(CustomPageEditVO req) {
        CustomPage customPage = req.getCustomPage();
        List<CustomPageData> customPageDataList = new ArrayList<>();
        if (customPage.getId() == null) {
            // 新建
            customPage.setCreatedAt(new Date());
            customPage.setUpdatedAt(new Date());
            customPage.setType(CustomPageTypeEnum.MERCHANT.getType());
            customPageMapper.insert2(customPage);
        } else {
            // 修改
            customPage.setType(CustomPageTypeEnum.MERCHANT.getType());
            customPage.setUpdatedAt(new Date());
            customPageMapper.updateByPrimaryKeySelective(customPage);

            customPageDataMapper.deleteByCustomPageId(customPage.getId());
        }

        req.getCustomPageDataList().stream().forEach(item -> {
            item.setCustomPageId(customPage.getId());
            item.setCreatedAt(new Date());
            customPageDataList.add(item);
        });
        customPageDataMapper.batchInsert2(customPageDataList);

        return new BaseResp();
    }

    @Override
    public ResultData<CustomPageEditVO> getCustomPageDetail(Long id) {
        CustomPageEditVO vo = new CustomPageEditVO();

        vo.setCustomPage(customPageMapper.selectByPrimaryKey(id));
        List<CustomPageData> customPageDataList = customPageDataMapper.findAllByCustomPageId(id);

        // 获取所有的商品,优惠券信息
        List<Long> spuIds = new ArrayList<>();
        List<Long> couponIds = new ArrayList<>();
        customPageDataList.stream().forEach(item -> {
            if (CustomPageDataTypeEnum.PRODUCT.getType().equals(item.getType())) {
                spuIds.add(item.getRelateId());
            }
            if (CustomPageDataTypeEnum.COUPON.getType().equals(item.getType())) {
                couponIds.add(item.getRelateId());
            }
        });

        Map<Long, Spu> spuMap = CollectionUtils.isEmpty(spuIds) ? new HashMap<>() : daoService.getSpuMap(spuIds);
        Map<Long, Coupon> couponMap = CollectionUtils.isEmpty(couponIds) ? new HashMap<>() : daoService.getCouponMap(couponIds);

        List<CustomPageDataVO> customPageDataVOList = new ArrayList<>();
        customPageDataList.stream().forEach(item -> {
            CustomPageDataVO customPageDataVO = new CustomPageDataVO();
            BeanUtils.copyProperties(item, customPageDataVO);
            if (CustomPageDataTypeEnum.PRODUCT.getType().equals(item.getType())) {
                customPageDataVO.setSpu(spuMap.get(item.getRelateId()));
            }
            if (CustomPageDataTypeEnum.COUPON.getType().equals(item.getType())) {
                customPageDataVO.setCoupon(couponMap.get(item.getRelateId()));
            }
            customPageDataVOList.add(customPageDataVO);
        });

        vo.setCustomPageDataList(customPageDataVOList);

        return new ResultData<>(vo);
    }

    @Override
    public BaseResp deleteCustomPage(Long id) {
        customPageMapper.deleteByPrimaryKey(id);
        customPageDataMapper.deleteByCustomPageId(id);
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<CustomPage>> getCustomPage(PageReq req) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (req.getType() != null) {
            if (req.getType().equals(CustomPageTypeEnum.MERCHANT.getType()) || req.getType().equals(CustomPageTypeEnum.ADMIN.getType())) {
                req.setTenantId(merchant.getTenantId());
            }
        } else {
            req.setType(CustomPageTypeEnum.MERCHANT.getType());
            req.setTenantId(merchant.getTenantId());
        }
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<CustomPage> list = customPageMapper.findAllPage(req);
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<List<TenantConfig>> getAllTenantConfig() {
        return new ResultData<>(tenantConfigMapper.findAll());
    }

    @Override
    public BaseResp editTenantConfig(TenantConfig req) {
        if (req.getId() == null) {
            req.setCreatedAt(new Date());
            req.setUpdatedAt(new Date());
            tenantConfigMapper.insert2(req);
        } else {
            req.setUpdatedAt(new Date());
            tenantConfigMapper.updateByPrimaryKeySelective(req);
        }
        return new BaseResp();
    }

    @Override
    public BaseResp deleteTenantConfig(Long id) {
        tenantConfigMapper.deleteByPrimaryKey(id);
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<ShopAmountVO>> getShopAmountPage(ShopAmountReq req) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<ShopAmountVO> list = shopAmountMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, Shop> shopMap = daoService.getShopMap(list.stream().map(ShopAmountVO::getShopId).collect(Collectors.toList()));
            List<Long> industryId = list.stream().map(ShopAmountVO::getIndustryFirstId).collect(Collectors.toList());
            industryId.addAll(list.stream().map(ShopAmountVO::getIndustrySecondId).collect(Collectors.toList()));
            Map<Long, Industry> industryMap = daoService.getIndustryMap(industryId);
            list.stream().forEach(item -> {
                item.setShopName(shopMap.get(item.getShopId()).getShopName());
                item.setShopAvatar(shopMap.get(item.getShopId()).getAvatar());
                item.setIndustryFirstName(industryMap.get(item.getIndustryFirstId()).getName());
                item.setIndustrySecondName(industryMap.get(item.getIndustrySecondId()).getName());
            });
        }
        ResultData<BasePageResp<ShopAmountVO>> result = PageHelpUtil.buildPage(list, page);
        ShopAmountRankVO rankVO = new ShopAmountRankVO();
        ShopAmount shopAmount = shopAmountMapper.findOneByShopId(merchant.getTenantId());
        if (req.getIndustryFirstId() == null) {
            Long totalRank;
            if (shopAmount != null) {
                totalRank = shopAmountMapper.countByAmountGreaterThan(shopAmount.getAmount()) + 1;
            } else {
                totalRank = shopAmountMapper.countAll() + 1;
            }
            rankVO.setRank(totalRank);
            rankVO.setAmount(shopAmount != null ? shopAmount.getAmount() : new BigDecimal(BigInteger.ZERO));
        } else {
            Long sameTotalRank;
            if (shopAmount != null) {
                sameTotalRank = shopAmountMapper.countByAmountGreaterThanAndIndustryFirstId(shopAmount.getAmount(), shopAmount.getIndustryFirstId());
            } else {
                sameTotalRank = shopAmountMapper.countByIndustryFirstId(req.getIndustryFirstId()) + 1;
            }
            rankVO.setRank(sameTotalRank);
            rankVO.setAmount(shopAmount != null ? shopAmount.getAmount() : new BigDecimal(BigInteger.ZERO));
        }
        result.getValue().setExtra(rankVO);
        return result;
    }

    @Override
    public BaseResp editShopAvatar(Shop req) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        shopMapper.updateAvatarById(req.getAvatar(), merchant.getTenantId());
        return new BaseResp();
    }

    @Override
    public BaseResp editShopNickname(Shop req) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        shopMapper.updateShopNameById(req.getShopName(), merchant.getTenantId());
        return new BaseResp();
    }

    @Override
    public BaseResp editShopReturnAddress(Shop req) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        shopMapper.updateReturnAddressById(req.getReturnAddress(), merchant.getTenantId());
        return new BaseResp();
    }

    @Override
    public BaseResp editShopAfterSaleAddress(Shop req) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        shopMapper.updateAfterSaleAddressById(req.getAfterSaleAddress(), merchant.getTenantId());
        return new BaseResp();
    }

    @Override
    public BaseResp editShopAfterSalePhone(Shop req) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        shopMapper.updateAfterSalePhoneById(req.getAfterSalePhone(), merchant.getTenantId());
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<ShopCollectionVO>> getShopCollectionPage(PageReq req) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        req.setShopId(merchant.getTenantId());
        List<ShopCollectionVO> list = shopCollectionMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(ShopCollectionVO::getUserId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                item.setUser(userMap.get(item.getUserId()));
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp editShopIntroduction(CompanyIntroduction req) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Tenant tenant = new Tenant();
        if (req.getContent() != null || req.getVideoUrl() != null) {
            tenant.setId(merchant.getTenantId());
            tenant.setContent(req.getContent());
            tenant.setVideoUrl(req.getVideoUrl());
            tenantMapper.updateContentAndVideoUrlAndUpdatedAtById(tenant);
        }
        if (req.getImageList() != null) {
            shopMapper.updateImageListById(req.getImageList(), merchant.getTenantId());
        }
        return new BaseResp();
    }

    @Override
    public ResultData<CompanyIntroduction> getShopIntroduction() {
        CompanyIntroduction vo = new CompanyIntroduction();
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Tenant tenant = tenantMapper.selectByPrimaryKey(merchant.getTenantId());
        Shop shop = shopMapper.selectByPrimaryKey(merchant.getTenantId());
        vo.setVideoUrl(tenant.getVideoUrl());
        vo.setContent(tenant.getContent());
        vo.setImageList(shop.getImageList());
        return new ResultData<>(vo);
    }

    @Override
    public BaseResp editAutoReplyFormat(String replyFormat) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        tenantMapper.updateAutoReplyFormatById(replyFormat, merchant.getTenantId());
        return new BaseResp();
    }

    @Override
    public BaseResp setStoreIdentity(Long userId) throws ResultCodeException {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        ShopCollection shopCollection = shopCollectionMapper.findOneByShopIdAndUserId(merchant.getTenantId(), userId);
        if (shopCollection == null) {
            throw new ResultCodeException(ResultCode.CANNOT_SET_AS_PROXY_IDENTITY);
        }
        User user = userMapper.selectByPrimaryKey(userId);
        Identity identity = identityMapper.selectOneByUserId(userId);
        if (user == null || identity == null) {
            throw new ResultCodeException(ResultCode.INCOMPLETE_USER_INFORMATION_CANNOT_SET_AS_PROXY_IDENTITY);
        }
        user.setLevel(UserLevelEnum.PARTNER_L1.getLevel());
        userMapper.updateByPrimaryKey(user);

        identity.setLevel(UserLevelEnum.PARTNER_L1.getLevel());
        identityMapper.updateByPrimaryKey(identity);
        return new BaseResp();
    }

    @Override
    public void agencyDiscount(Long userId, BigDecimal discount) throws ResultCodeException {
        User user = userMapper.selectByPrimaryKey(userId);
        if (!user.getLevel().equals(UserLevelEnum.PARTNER_L1.getLevel())) {
            throw new ResultCodeException(ResultCode.DISCOUNTS_NOT_AVAILABLE_FOR_USER_IDENTITY);
        }
        user.setAgencyDiscount(discount);
        userMapper.updateByPrimaryKey(user);
    }
}